<?php

namespace MLM\Model\Generic\Object;

use MLM\Model\Generic\Object;

class Mapper extends Object {

    const MODE_EXCLUDE = 0;
    const MODE_INCLUDE = 1;

    private $_map = array();
    
    public function __construct($data = array(), $map = array()) {

    $properties = array();
    foreach ($map as $key => $item) {
      if ($item instanceof Map) {
        $this->_map[$item->real] = $item;
        $properties[] = $item->alias;
      } else {
        $this->_map[$key] = new Map($key, $item);
        $properties[] = $item;
      }
    }

    parent::__construct($data, $properties);
  }
  
  public function map($real, $alias = null, $pseudo = false) {

    return new Map($real, $alias, $pseudo);
  }

  public function get($name) {

    return $this->__get($this->_map[$name]->alias);
  }

  public function set($name, $value) {

    return $this->__set($this->_map[$name]->alias, $value);
  }

  public function push($data, $map = true) {

    if ($map && $this->_hasProperties) {

      if (is_array($data)) {

        foreach ($data as $name => $value) {
          if (array_key_exists($name, $this->_map) === false) {
            parent::notice('push', $name);
          } else {
            $this->_data[$this->_map[$name]->alias] = $value;
          }
        }

      }

    } else {

      /* raw push */
      parent::push($data);

    }

  }

  public function pull($properties = array(), $mode = self::MODE_EXCLUDE, $map = true) {

    /* use mapping */
    if ($map) {

      /* init output */
      $data = array();
      if ($mode == self::MODE_INCLUDE) {

        /* include only data in properties */
        foreach ($this->_map as $key => $value) {
          if (!$value->pseudo) {
            if (array_search($key, $properties) !== false) {
              $data[$key] = $this->_data[$value->alias];
            }
          }
        }

      } else {

        /* exclude data in properties array */
        foreach ($this->_map as $key => $value) {
          if (!$value->pseudo) {
            if (array_search($key, $properties) === false) {
              $data[$key] = $this->_data[$value->alias];
            }
          }
        }

      }

    } else {

      /* raw pull */
      $data = $this->_data;

    }

    return $data;
  }

}
